<?php
// $Id$

/*
 * Copyright 2011 Google Inc.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/**
 * @file
 * Functions needed for the rebuild process
 */

/**
 * Rebuilds the sitemaps files through a batch process
 */
function googlevideositemaps_rebuild_batch($force, & $context=false){
	global $base_url;
	$cont = 1;
	$type = 'video';
	$result = db_query(
		"SELECT 
			n.nid AS playpage,
			n.title, 
			nr.body AS description, 
			nr.timestamp AS published, 
			ctv.field_video_data AS thumbdata,
			ctv.field_duration_value AS duration, 
			ctv.field_expiration_date_value as expiration, 
			ctv.field_regional_restrictions_value AS restrictions, 
			ctv.field_tags_value AS tags, 
			ctv.field_category_value AS category, 
			ctv.field_family_friendly_value AS family_friendly, 
			f.filepath AS location 
		FROM {node} n 
			INNER JOIN {node_revisions} nr 
				ON (n.nid = nr.nid and n.vid = nr.vid)  
			INNER JOIN {content_type_video} ctv 
				ON (nr.nid = ctv.nid and nr.vid = ctv.vid) 
			INNER JOIN {files} f 
				ON (ctv.field_video_fid=f.fid) 
		WHERE n.type = '$type' 
		ORDER BY nr.timestamp ASC"
	);
	
	if($result != null && !empty($result)){
		$videos = googlevideositemaps_rebuild_check_update($result ,$force);
		if( $videos ){
			googlevideositemaps_rebuild_clear();

			$data = googlevideositemaps_rebuild_format_data($videos);
			
			$res = googlevideositemaps_rebuild_create_files($data);
			
			drupal_set_message(t( implode("<br/>" , $res) ));	
		}
		else{
			drupal_set_message(t('No changes detected to update files. Rebuild skipped.'));
		}
	}
	else{
		drupal_set_message(t('No entries to build the files'));
	}
}

/**
 * Checks id the files need to be updated
 */
function googlevideositemaps_rebuild_check_update($result, $force){
	$file = file_directory_path() . '/googlevideositemaps.stats';
	$count = 0;
	$ids = array();
	$videos = array();
	
	while($video = db_fetch_array($result)){
		$videos[] = $video;
		$ids[] = $video['playpage'];
		$count++;
	}
	$ids = implode(':',$ids);
	
	if(file_exists($file)){
		$stats = file($file);
		
		if( count($stats) != 2 || $stats[0] != $count || $stats[1] != $ids || $force){
			file_put_contents($file,$count . "\n" . $ids);
			return $videos;
		}
	}
	else{
		file_put_contents($file,$count . "\n" . $ids);
		return $videos;
	}
	return false;
}

/**
 * Deletes all the older video sitemaps files
 */
function googlevideositemaps_rebuild_clear(){
	$files_dir = file_directory_path();
	if ($dir_id = opendir($files_dir)) {
  	while (false !== ($file = readdir($dir_id))) {
			if( $file != '..' && $file != '.' && strpos( $file, GOOGLEVIDEOSITEMAP_FILEPATTERN) ){
      	$b = file_delete($files_dir . '/' . $file);	
      }
    }
   closedir($dir_id);
	}
}

/**
 * List the video sitemaps files already created. Returns an array with file nmes and links to access them
 */
function googlevideositemaps_rebuild_list(){
	global $base_url;
	$result = array();
	$files_dir = file_directory_path();
	if ($dir_id = opendir($files_dir)) {
  	while (false !== ($file = readdir($dir_id))) {
			if( $file != '..' && $file != '.' && strpos( $file, GOOGLEVIDEOSITEMAP_FILEPATTERN) ){
      	$file_stat = stat($files_dir . '/' . $file);
				
				$result[] = array(
      		'name' => $file,
      		'location' =>  $base_url . '/' . $files_dir . '/' . $file,
					'size' => $file_stat['size'],
 					'updated' => date(DATE_ATOM , $file_stat['mtime'])
      	);
			}
    }
   closedir($dir_id);
	}
	return $result;
}

/**
 * Formats the data retrieved from database to an XML string
 */
function googlevideositemaps_rebuild_format_data($data){
	global $base_url;
	$file_count = 1;
	$size = 1000;
	$quantity = 0;
	$results = array();
	$errors = array();
	
	$clean_url = false;
	$apache_modules = ( (function_exists('apache_get_modules') ) ? apache_get_modules() : false );
	if($apache_modules != false && in_array('mod_rewrite',$apache_modules)){
		$clean_url = true;
	}
	
	foreach($data as $video){
		// a little less of 10MB due to some calculation issues that may ocurr
		if($size > (1022 * 1022 * 10) || $quantity > 49000){
			$file_count++;
			$size = 1000;
			$quantity = 0;
		}
		$thumb_info = unserialize($video['thumbdata']);
		
		if(
			$video['playpage'] != '' &&
			$video['title'] != '' &&
			$video['description'] != '' &&
			$video['location'] != '' &&
			($thumb_info['video_thumb_file'] != '' || $thumb_info['video_thumb'] != '')
		){
			$result = '<video>';
			if($clean_url){
				$result .= '<url>' . $base_url . '/node/' . $video['playpage'] . '</url>';
			}
			else{
				$result .= '<url>' . $base_url . '/?q=node/' . $video['playpage'] . '</url>';
			}
			
			$result .= '<title>' . $video['title'] . '</title>';
			$result .= '<description>' . $video['description'] . '</description>';
			$result .= '<file>' . $base_url . '/' . $video['location'] . '</file>';
			
			
			$result .= '<image>' . $base_url . '/' . (($thumb_info['video_thumb_file']) ? $thumb_info['video_thumb_file'] : $thumb_info['video_thumb']) . '</image>';
			
			$result .= '<publication_date>' . date(DATE_ATOM , $video['published']) . '</publication_date>';
			
	    if($video['expiration'] != ''){
				$exp_date = explode('/' , $video['expiration']);
				$exp_date = date(DATE_ATOM , mktime(23 , 59 , 59 , $exp_date[0] , $exp_date[1] , $exp_date[2]));
	    	$result .= '<expiration>' . $exp_date . '</expiration>';
			}
			
			if($video['duration'] != ''){
				$result .= '<duration>' . $video['duration'] . '</duration>';
			}
			
			if($video['restrictions'] != ''){
				$result .= '<restrictions>' . t($video['restrictions']) . '</restrictions>';
			}
			
			if($video['family_friendly'] != ''){
				$result .= '<family_friendly>' . $video['family_friendly'] . '</family_friendly>';
			}
			
			if($video['category'] != ''){
				$result .= '<category>' . $video['category'] . '</category>';
			
			}
			if($video['tags'] != ''){
				$result .= '<tags><tag>';
				$result .= implode('</tag><tag>' , explode(',' , t($video['tags']) ));
				$result .= '</tag></tags>';
			}
			$result .= '</video>';

			$size += googlevideositemaps_rebuild_calculate_size($video);
			$quantity++;
			$results['videos'][$file_count][] = $result;
		}
		else{
			$results['errors'][] = "Insufficient data for video: " . $video['playpage'] . "-" . $video['title'] . "-" . $video['description'] . "-" . $video['location'];
		}
	}
	
	return $results;
}

/**
 * Creates the files for video sitemaps. The files are being created taking into account the size (maximum 10MB) and quantity (maximum 50K entries)
 */
function googlevideositemaps_rebuild_create_files($data){
	$ret = array();
	if(is_array($data['videos'])){
		$xslDoc = simplexml_load_file(drupal_get_path('module', 'googlevideositemaps') . "/googlevideositemaps.xsl");
	  $xsl		= new XSLTProcessor();
	  $xsl->importStylesheet($xslDoc);
		
		foreach($data['videos'] as $fid => $file_data){
			$xmlData	= simplexml_load_string('<videos>' . implode(' ',$file_data) . '</videos>' );
		  $xmlFile	= $xsl->transformToXML($xmlData); 
		  $file = variable_get('googlevideositemaps_file_pattern', 'videos') . GOOGLEVIDEOSITEMAP_FILEPATTERN . str_pad($fid,4,'0',STR_PAD_LEFT) . t('.xml');
			
			file_save_data($xmlFile, $file, $replace = FILE_EXISTS_REPLACE);
			
			$ret[] = $file . ": File created" . googlevideositemaps_rebuild_ping($file);
		}
		
		if(isset($data['errors'])){
			foreach($data['errors'] as $err){
				$ret[] = $err;	
			}
		}
	}
	return $ret;
}

/**
 * Ping Google Webmaster tool with the sitemap updated
 */
function googlevideositemaps_rebuild_ping($file){
	global $base_url;
	$files_dir = file_directory_path();
	$file_url =  $base_url . '/' . $files_dir . '/' . $file;
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, GOOGLEVIDEOSITEMAP_PING . $file_url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$output = curl_exec($ch);
	curl_close($ch);
	if(strpos($output,'<h2>Sitemap Notification Received</h2>') !== false){
		return " - Sitemap Notification Received";
	}
	return " - Sitemap Notification Error";
}


/**
 * Calculates the size of each video entry
 */
function googlevideositemaps_rebuild_calculate_size($video){
	global $base_url;
	$thumb_info = unserialize($video['thumbdata']);
	
	//initial url + video tags size
	$size = 38;
	
	//size of the play page
	$size += strlen($base_url) + strlen($video['playpage']) + 17;
	
	//size of the title
	$size += strlen($video['title']) + 27;
	
	//size of the thumbnail
	$size += strlen($base_url) + strlen( (($thumb_info['video_thumb_file']) ? $thumb_info['video_thumb_file'] : $thumb_info['video_thumb']) ) + 43;
	
	//size of the description
	$size += strlen($video['description']) + 39;
	
	//size of the video file
	$size += strlen($base_url) + strlen($video['location']) + 40;
	
	//size of the publication date
	$size += 74;
	
	//size of the expiration date
	if($video['expiration'] != ''){
		$size += 72;
	}
	
	//size of the restrictions
	if($video['restrictions'] != ''){
		$size += strlen($video['restrictions']) + 50;
	}
	
	//size of duration
	if($video['duration'] != ''){
		$size += strlen($video['duration']) + 31;
	}
	
	//size of tags
	if($video['tags'] != ''){
		$size += strlen($video['tags']) + (22*2);
	}
	
	//size of category
	if($video['category'] != ''){
		$size += strlen($video['category']) + 31;
	}
	
	//size of famili friendly
	if($video['family_friendly'] != ''){
		$size += strlen($video['family_friendly']) + 45;
	}
	
	return $size;
} 